bpy.ops.bridge_edge_loops() vs bmesh.ops.bridge_loops()
Rather late but was trying to work this out myself recently and thought this might be useful to anyone who comes across this issue in future. bpy.ops.bridge_edge_loops() functionality can be replicated by calling bmesh.ops.subdivide_edges() after bmesh.ops.bridge_loops()
e.g. to replicate bpy.ops.mesh.bridge_edge_loops(interpolation='LINEAR', smoothness=1, number_cuts=4)
ret = bmesh.ops.bridge_loops(bm, edges=bm.edges)
bmesh.ops.subdivide_edges(
    bm,
    edges=ret['edges'],
    smooth=1.0,
    smooth_fallof='LINEAR',
    cuts=4)