I'm not entirely sure why the loaded attribute is even available on the root element, because what it does is inherently impossible to evaluate at that level.
As opposed to rendered, which determines whether any representation of the component will be sent to the consumer, loaded determines whether or not the component is even created. So if rendered is false, it just doesn't display... if loaded is false, it doesn't even exist. The component needs to exist for the view tag attributes to be evaluated, so it's too late by then to stop it from existing since it needs to exist in order to be told not to exist.
As a result, in order to use loaded to suppress the entire control, the attribute needs to be set on the control reference. In other words, when adding the control to an XPage (or another custom control), set a loaded expression on the tag for the control. If it evaluates to false, then the control will never be loaded.
Remember, all of this ends up executing as Java... if you block construction of a class instance, you don't have a class instance to ask whether it should have been constructed. Conversely, if you create a class instance, then ask it whether it should exist... too late, it already exists. If the custom control should own the logic for whether its contents should exist, then specifying that logic in the loaded attribute of a single child container is the "right" approach.