You're better off using bpy.data.objects to manipulate them. This way you don't need to rely on what is selected, all you need is the objects name.
mod_name = 'My-Mirror-Modifier'
for obj in bpy.data.collections["My-Collection"].all_objects:
if obj.type == 'MESH':
mod = obj.modifiers.new(mod_name, 'MIRROR')
For Blender >2.80 this will work.
Select all your objects and run this in the scripting panel.
for object in bpy.context.selected_objects:
obj_loc = object.location
new_empty = bpy.data.objects.new( "empty", None )
new_empty.location = obj_loc
object.parent = new_empty # swap this line around to parent the other way
For operators use context.
Given the self in the question code, making the assumption you are writing an operator
Further to the answer of @RoufirHassan by way of explanation, looping over the collection objects de-selecting and selecting single, was not changing the active object. Adding context.object to print statement would confirm this.
Is the active ...
Put them in a collection
IMO the simplest way to do this is, as suggested
scene_lights = [ob for ob in scene.objects if ob.type == 'LIGHT']
One light object could have the same light data as any or all of the lights in a scene. Even if there are few lights, checking that the data belongs to an object in the scene could prove less efficient than above.
Select all the meshes in your collection and add a mirror modifier.
But as you said it will only mirror the active object ( active object = last object selected with different colored outline). So in order to mirror every single object just type (Ctrl+L) > modifiers. It will link all objects with the same modifier.
You can use it for any other modifiers.
You can test whether menu_func is already part of _draw_funcs list and if so, do not prepend:
if hasattr(bpy.types.VIEW3D_MT_uv_map.draw, '_draw_funcs'):
if menu_func.__name__ not in (f.__name__ for f in bpy.types.VIEW3D_MT_uv_map.draw._draw_funcs):