Problem with for loop in vertices
You have to toggle out of edit mode after deselecting all vertices to solve your issue.

bpy.ops.object.mode_set(mode='OBJECT')          #SWITCH TO OBJECT MODE
a.select = True                                 #SELECT VERTEX
bpy.ops.object.mode_set(mode='EDIT')            #SWITCH TO EDIT MODE 
bpy.ops.object.hook_add_newob()
bpy.ops.mesh.select_all(action='DESELECT')      #DESELECT VERTICES
bpy.ops.object.editmode_toggle()                


For better understanding why you have to leave the edit mode this answer maybe helps.



Edit: In terms of better error handling I suggest you to write a bit more functional and split the code in useful pieces. The positive side effect would be that you have much more control, because you also can cache your states. I assume from the code above you want to have following functions:


create empties from all verticies of the selected object
add and assign hook modifiers for all empties to the selected object
create a group or add empties to a group


For e.g. this function creates the empties and returns a list of the new ones:

# -----------------------------------------------------------------------
# create empties from vertices
# -----------------------------------------------------------------------
# parameter: mesh object
# returns: list of new empty objects

def createEmptiesFromVerts (obj):

    # get object data
    objMesh = obj.data
    vertList = [vert for vert in objMesh.vertices]

    # create a list for the new empties
    emptyList = []

    for i in range(len(vertList)):

        # get local coordinate
        vertCoordinate = obj.data.vertices[i].co
        vertCoordinate = obj.matrix_world * vertCoordinate

        # add the empty    
        bpy.ops.object.add(type='EMPTY', location=vertCoordinate)
        newEmpty = bpy.context.active_object
        newEmpty.location = vertCoordinate
        newEmpty.empty_draw_size = newEmpty.empty_draw_size # / 4
        bpy.ops.object.select_all(action='TOGGLE')
        bpy.ops.object.select_all(action='DESELECT')

        # append the new empty to the list
        emptyList.append(newEmpty)

    # set object to original state
    bpy.context.scene.objects.active = obj
    obj.select = True

    # return the new empties  
    return emptyList


With this incoming list you can go on with the next function and assign the hook modifiers.

# -----------------------------------------------------------------------
# create hook modifiers
# -----------------------------------------------------------------------
# parameter: mesh object, hook object list
# returns: assigned hooks list, assigned modifier list

def hooksFromVerts (obj, hookObjs):

    # get object data
    objMesh = obj.data
    vertList = [vert for vert in objMesh.vertices]

    # create list to save all assigned hooks
    assignedHooks = []
    assignedModifiers = []

    for i in range(len(vertList)):

        bpy.ops.object.mode_set(mode="EDIT")
        bpy.ops.mesh.select_all(action="DESELECT")
        bpy.context.tool_settings.mesh_select_mode = (True , False , False)
        bpy.ops.object.mode_set(mode="OBJECT")

        # get local coordinate of vertex
        vertCoordinate = obj.data.vertices[i].co
        vertCoordinate = obj.matrix_world * vertCoordinate

        bpy.context.object.data.vertices[i].select = True
        bpy.ops.object.mode_set(mode="EDIT")

        # assign hook if coords of vert and hook object are equal
        for n in hookObjs:
            if vertCoordinate == n.location:
                #modifierName = "Hook" + str(i+1)
                modifierName = "Hook_" + n.name
                obj.modifiers.new(modifierName, type='HOOK')
                obj.modifiers[modifierName].object = n
                bpy.ops.object.hook_assign(modifier=modifierName)

                # append the hook objects to the list
                assignedHooks.append(n)

                # append modifiers
                assignedModifiers.append(modifierName)

    # set object to original state    
    bpy.ops.mesh.select_all(action = 'DESELECT')
    bpy.ops.object.mode_set(mode ="OBJECT")

    # set object to original state
    bpy.context.scene.objects.active = obj
    obj.select = True

    # return assogned hooks objects and modifiers
    return assignedHooks, assignedModifiers


As last step you can create a function that creates a group if it not exists and throw your empties in it. To call this is much more easier and for us more readable at all:

# get the object
selectedObj = bpy.context.active_object

if selectedObj.type == 'MESH':

    # create empties
    generatedEmpties = createEmptiesFromVerts(selectedObj)

    # create hooks
    generatedHooks = hooksFromVerts(selectedObj, generatedEmpties)

    # remove modifiers
    #removeModifiersByNameList(selectedObj, generatedHooks[1])

    # create or add to group
    generatedGroup = addObjectsToGroup("testgroup", generatedHooks[0])

else:
    print ("please select a mesh object.")


Hope this helps!