From reading the 3.0 code, it appears to be:
TextureCache holds all loaded images/sprite sheets.
SpriteBatchNode has it's image in a TextureCache, but makes it easy for Cocos to batch draw calls.
SpriteFrameCache holds all the image positions on sprite sheets, so you don't have to get the individual image frames with hard-coded coordinates.
Sprites are created from the SpriteFrameCache to make it easy to access them.
It seems as though you can load textures into the TextureCache async, then afterwards call SpriteFrameCache addSpriteFramesWithFile which will automatically search for an existing loaded texture instead of loading a new one. This is handy if you load all your assets at the start of an app with a progress bar or don't want to lock up the platform.
Just remember that SpriteBatchNodes do all their draws at once. For example, if you have a sprite from batch node A between two sprites from batch node B, then B will have two draw calls. If you only have a couple sprites it may not affect you, but many sprites with this drawing problem will have a big performance impact.