I consider this scenarios for deploying High Available Python web apps:
For load balancer I consider HAProxy
For production HTTP sever I consider Nginx
For wsgi servers I mean servers which directly handle wsgi app (gevent, waitress, uwsgi...)
-* means one to many connection
- means one to one connection
There is no static content to serve. So I wonder if production HTTP server is needed.
EDIT: At the time of writing, this answer reflected the state of WebSocket support in uWSGI and nginx (they had none), but since then, they've grown support for it. I'll leave the answer intact for historical interest.
1: You almost certainly want an HTTP reverse proxy like nginx to deal with "spoon feeding" slow or stupid client programs; some of your users will be on slow connections; the reverse proxy usually can wait for the request to be fully received before contacting the application, then slurp the full response from the application quickly (so that it can move on to other requests), and then feed that back to the client as slowly as they require. If you're using a reverse proxy anyways, there's not much reason to consider a tcp level loadbalancer, too; since the reverse proxy can already solve that problem. This is especially true since tcp load balancers aren't application aware, and can't skip upstream hosts that are "reachable" but "sick", they will happily proxy for servers that are returning "500 Internal Server Error" responses to health check requests. they're usually needed only at the extreme edges of your network at very high load.
2: which application container is right for you depends as much on the application as it does on the shape of your workload; to take advantage of async containers like tornado, your application must be written in a special way; and can't use all of the nice/convenient frameworks that are available for wsgi in general; on the other hand, you will need them for some features like long polling and especially websocket, these features are not practical (or even possible) in things like uwsgi.
but, not all containers are created equal; many speak only HTTP, which is not a CPU friendly protocol, containers like uwsgi are designed to optimize the http parsing work so that only the reverse proxy has to do it, from there out, easily parsed binary protocols are passed from one process to the next.
3: websocket is still very new, and support in python is sparse. The most mature options seem to be the implementations available in tornado and in twisted; Neither can be hosted in uwsgi, and cannot be proxied behind nginx. there are other reverse proxies that can handle websocket, though, for example, varnish.