Creating objects with a 'for loop' and setting each new one a keyframe within the 'for loop' So I wish to have a script which creates an object then set's it keyframe at a frame, 'f', before creating another object and setting a keyframe at a new frame, say f+1. However it always sets the keyframe to the first object created and not to the newer ones and using bpy.ops.data.object['Wave'].select = True doesn't work as it just selects the first plane created and not the others (due to the fact the others are named Wave.001 for example. I thought about turning the name into a string but that seemed like an improbable solution. When I ran this script with a more simple example of a plane it seemed to work... Here's the script I'm using for the wave:

import bpy
import math
scn = bpy.context.scene

numY = 10
freq = 1
amp = 1
scale = 1

for numX in range (2, 20):
    scn.frame_current = numX - 2
    verts = []
    faces = []

    for i in range (0, numX):
        for j in range (0, numY):
            x = scale * i
            y = scale * j
            z = scale*((amp*math.cos(i*freq))+(amp*math.sin(j*freq)))

            vert = (x,y,z)
            verts.append(vert)

    count = 0
    for i in range (0, numY*(numX-1)):
        if count &lt; numY-1:
            A = i
            B = i+1
            C = (i+numY)+1
            D = (i+numY)

            face = (A,B,C,D)
            faces.append(face)
            count = count + 1
        else:
            count = 0

    mesh = bpy.data.meshes.new("Wave")
    object = bpy.data.objects.new("Wave",mesh)

    object.location = (0,0,0)
    bpy.context.scene.objects.link(object)

    mesh.from_pydata(verts, [],faces)
    mesh.update(calc_edges=True)
    bpy.ops.data.object['Wave'].select = True
    bpy.ops.anim.keyframe_insert_menu(type='Location')


The strange thing was that without the bpy.ops.data.object['Wave'].select = True the script fails with it outlining bpy.ops.anim.keyframe_insert_menu(type='Location') as the issue. I don't see a difference between this and the simpler cube example though - which works fine without the need of selecting the Plane. Here's the code for the plane example :

import bpy
from mathutils import Vector

scn = bpy.context.scene
scn.frame_start = 0
scn.frame_end = 20
scn.frame_current = 0
for f in range (0, 20):
    bpy.ops.object.add(type='MESH')
    Plane = bpy.context.object
    Plane.name = "Plane"
    PlaneMesh = Plane.data

    verts = [(0,0,0), (0,5,0), (0,5,5), (0,0,5)]
    faces = [(0,1,2,3)]

    PlaneMesh.from_pydata(verts, [], faces)
    PlaneMesh.update()
    scn.frame_current = f
    bpy.ops.anim.keyframe_insert_menu(type='Location')

scn.frame_current = 0


Can anyone please help me understand what's going on...?
Here is your script (a) doing what I think you want it to do.  It makes a mesh object at each frame, and adds a location keyframe at the frame it was created in script.

If you are using an operator, need to be in, or set the context it requires. Make a new object obj context with context.scene.objects.active = obj.  If it works on selected objects, like say join, need to make sure other objects are (de)selected correctly by setting obj.select accordingly on each.

Going to use bpy_struct.keyframe_insert(...) rather than the operator.  This will be quicker, especially for high numbers. 

import bpy
from math import sin, cos
scn = bpy.context.scene

numY = 10
freq = 1
amp = 1
scale = 1

for numX in range (2, 20):
    verts = []
    faces = []

    for i in range (0, numX):
        x = scale * i
        for j in range (0, numY):                
            y = scale * j
            z = scale * amp * (cos(i * freq) + sin(j * freq))
            vert = (x, y, z)
            verts.append(vert)

    count = 0
    for i in range (0, numY * (numX - 1)):
        if count &lt; numY - 1:
            A = i
            B = i + 1
            C = (i + numY) + 1
            D = (i + numY)

            face = (A, B, C, D)
            faces.append(face)
            count = count + 1
        else:
            count = 0

    mesh = bpy.data.meshes.new("Wave")

    mesh.from_pydata(verts, [], faces)
    mesh.update(calc_edges = True)

    obj = bpy.data.objects.new("Wave", mesh)

    obj.location = (0, 0, 0)
    scn.objects.link(obj)
    obj.keyframe_insert("location", frame=numX, group="Location")