One more piece of info...
Even when the panel is already enabled, the panel size is still sometimes calculated incorrectly due to the label. I was able to get it working 100% with this:
label.text="something";
label.MarkAsChanged();
label.UpdateAnchors();
Bounds bounds = NGUIMath.CalculateRelativeWidgetBounds(label.transform);
// bounds is now always correct
If either MarkAsChanged() or UpdateAnchors() is missing, the label size is not updated immediately. Is this a bug, or just something we need to be aware of (I don't see any mention of this in the docs)?
Despite this fix, the label is still not positioned correctly if the panel is disabled initially (and re-enabled just before the positioning code). The size is correct, but the position is not (the label is anchored to another label, and I called MarkAsChanged() and UpdateAnchors() on that label first).
[edit] Oops, I used the wrong term. Everywhere I wrote "panel", I meant "UI Widget". Sorry about that. I named each of my widgets with "panel", since I use them as floating windows on my UI.