Before diving into wrapper code and unless you have a simple way of tracing C++, add this line:
_root.LookupCppEntity('kRed').__get__(_root)
just before the CreatePyROOTApplication() call. See whether it passes that.
Point being that in terms of pure initialization, the only difference should be wrapper creation (I’m assuming that the PyROOT dictionary is already loaded, but that one for sure is pulled in by CreateScopeProxy( ‘PyROOT::TPyROOTApplication’ ), which so far seems to be harmless enough).