Cache static files by hash

Implements #2734.

Deployment note: `GRATIPAY_ASSET_URL` needs to be changed to `https://assets.gratipay.com/` on Heroku. I don't think we'll need to change anything on the CDN side, can you confirm that @whit537 ?
Algorithm functions should return a dictionary that will be used to update the current algorithm run state. How did we end up with `return request` here? Why doesn't it cause an error when we try to `state.update(new_state)`?