Why does fire take so long to render?
Because fire is a volume, and volume rendering is slow. First of all, the baking you did doesn't help with rendering, it just caches the simulation itself. Anyway, the problem with rendering volumes is that you can't just sample the shader once at the surface like you can for solid objects. To render a volume, you need to evaluate the shader and sample what light is available multiple times along the transit through the volume. The finer the detail in the volume, the more steps you need to sample. The distance between steps in controlled by the "step size" attribute:  The distance is in meters, although the property doesn't show as distance for some reason. You don't need a step length any smaller than 1/2 the size of the smallest volume detail. For a smoke/fire sim, that would be the size of your voxels. You can find this for Blender's smoke sim by getting the dimensions of your domain, and plugging the length of the longest size into the formula: voxel size + length / (base res * (hi-res level + 1)). So a 10m domain with 80 res and 2 hi-res divisions would be 10 / (80 * (2+1)), or about 4cm.

There is also a "max steps" option you can use to force it to stop at some point along the path, although I'd recommend avoiding this control. Running out of steps mid-volume can potentially give some weird shading.

Additionally, if you're using the volume scatter shader, rays can be scattered (aka deflected) during the volume transit. And if your volume bounces is set greater than 0 under render settings > light path? That scattered path can scatter again. So higher values for volume bounces can increase render times a lot. Too few volume bounces can lead to dark volumes, especially for highly reflective clouds such as water vapor. You can compensate for this by adding some (more) emission to the volume if needed.

One way you can optimize a bit for smoke and the like is to prevent the shaders from running if the density is below a certain threshold. The node setup looks like this: 

If the density is below the value set in the "less than" math node, it will output 0, causing the mix shader to switch to it's second socket, which as no shader. Thus, the volume closures are only executed if there's a enough density for it to matter. Figuring out the proper value for the less than node might take some trial and error.