This line
with app.app_context():
f.g.foo = "bar"
Since you are using the "with" keyword, once this loop is executed, it calls the __exit__ method of the AppContext class. See this. So the 'foo' is popped out once done. Thats why you don't have it available again. You can instead try:
ctx = app.app_context()
f.g.foo = 'bar'
ctx.push()
Until you call the following, g.foo should be available
ctx.pop()
I am howver not sure if you want to use this for the purpose of caching.