In C/C++ an array and a pointer are treated the same. So if you have a routine that takes a TreeNode *, the compiler will accept either of the following.
TreeNode nodes[10];
TreeNode node;
TreeNode *node_ptr;
routine(nodes);
routine(&node);
routine(node_ptr);
So a double pointer is a pointer to either one of these. In some cases it is a pointer to a pointer:
TreeNode *node;
routine(&node); // In this case "routine" will most likely modify what node points to
And in some cases it is a pointer to an array:
TreeNode nodes[10];
routine(&nodes); // This is not normal, but in this case the contents on "nodes" is probably of interest to "routine"
It just depends on the application.
In your case, if Children was declared as struct TreeNode *Children[]; (An array of pointers) it probably would have been clearer, but since you do not know how many pointers you have you must allocate all the memory dynamically.
I could go on here, but this post would get way too long. I hope these examples help.