Why do I need to Destroy() popup menus and dialogs?
The need to call Destroy revolves around C++ object ownership. Normally a wx.Menu is owned by the menubar or parent menu that it is attached to, and since the menubar is owned by the frame and since frames Destroy() themselves when they are closed, then when the frame is destroyed then everything it owns, including the menubar and the menus, are destroyed too so we don't have to worry about managing that cleanup from wxPython. The same approach works for all the child windows as well, they are owned by their parent window.
But a menu used for a popup menu is not owned by anything else, so the above rule breaks down a bit. The Pythonic thing to do is to make it act like the C++ object is owned by the Python proxy object, then when the proxy is destroyed the C++ menu object will be too. Unfortunately since most wx C++ objects hold a reference to their Python proxy (to be able to implement some of the other wxPython magic) that wouldn't work since there would be a reference cycle that couldn't be broken by the garbage collector since one of the references is held by a C++ object. (Plus, I was using this approach long before Python even had a cyclic garbage collector.) So that means that you need to call Destroy yourself so the C++ object will go away and then since it decref's its reference then the Python proxy object goes away too.
Dialogs also fall into this same pattern because the C++ object does not automatically destroy itself when it is closed like frames do. This is because the typical use case for dialogs is that you access values from its widgets after ShowModal has returned. So because of the extra reference on the C++ side you need to call Destroy for every dialog yourself.