[As requested by Koba, I am reposting my entry here in this new thread.]
Original post:
Here’s my final script, .blend file, and animation.
Since this contest relies on OpenGL rendering, if anyone wants to test this script but has a slow PC/graphics card, you might want to lower the number of butterflies to something like 20 so the screen updates are okay.
To run it, just download the .blend file and press ALT A.
A new bunch of butterflies is created each time this script is executed for the first time in a Blender session. If you reload the entire file or exit/restart Blender and reload the file, a new batch of butterflies will appear.
The script was designed to survive multiple sessions of Blender by using a simple but specially named and invisible cube to indicate if the script has been initialized since, as per the contest instructions, we were to begin with the one butterfly and go from there.
Since the butterfly structure was also a mandatory thing to follow for the contest, there arose a new problem of having to create a “flap wing” routine for two wings that were to be a single mesh.
I solved this by using a mirror modifier on the wing, so the resulting mesh is indeed two wings from one mesh, and using vertex group assignments.
The vertex group assignments help the script determine which verts need to be moved every few frames.
Randomness is the dominant factor in this script, with some slight wavering/guidance from a mathematical sin (as in sine) function.
If your GPU is fast enough to handle it, it’s interesting to rotate the display while performing an ALT A animation preview to see how the routines work out over hundreds of frames.
Each butterfly has its own direction, path, and flapping state. Each path and rotation are randomly incremented/decremented every few frames to emulate the sharp and fluttery flight of a lively group of butterflies.
A possible future use of such a script would be to commit each object’s location/rotation to corresponding IPO curves, so as to bake the motion.
The script is invoked using Blender’s internal script link service. In prior versions of Blender, I recall having to reestablish script links upon loading such a .blend file with a script.
The type of script link used here is World/frame change, and it points to the butterflies script in the text panel.
Obviously, due to render limitations of this particular challenge, there was little potential for any fanciness. At most I was able to get a pretty good OpenGL shaded look out of Blender 2.44. I suppose with the new SOC realtime OpenGl project that such renders will look substantially nicer 
The script (works and is included with enclosed .blend file below):
###########################################################
# Blender Artists Python Challenge # 2
# ("A Swarm of Butterflies" animation)
# Script by RobertT
# Status: Final Submission
# Designed and tested in Blender 2.44
#
#
# Please note: This script uses Blender's script links
# function. To run this script, do NOT press ALT P.
# Instead, press ALT A in the 3D VIEW to watch the
# animate come to life. Press ESC when done.
# You can also render out the animation using the
# ANIM button or perform a 3D View render by
# holding the CTRL KEY when clicking the render
# button in the 3D View.
# Import the things we will need to make this script work
import Blender
from Blender import Scene, Object, Mesh, Mathutils
from Blender.Mathutils import Rand
from math import sin
###########################################################
# This user-definable variable controls how many
# butterflies are created for the animation.
# This can only be changed upon first loading
# this unmodified blend file and running the script.
howManyButterflies = 111
currentScene = Scene.GetCurrent()
currentContext = currentScene.getRenderingContext()
currentFrame = currentContext.cFrame
###########################################################
# Place the Butterflies at random locations, rotations,
# and resize them slightly randomly as well
def randomizeButterflyLocation(butterflyNumber, rX, rY, rZ, rR):
emptyObject = "butterflyEmpty.%03d" % butterflyNumber
#print emptyObject, rX, rY, rZ
butterflyEmpty = Blender.Object.Get(emptyObject)
butterflyEmpty.LocX += rX
butterflyEmpty.LocY += rY
butterflyEmpty.LocZ += rZ
butterflyEmpty.RotX += rR
butterflyEmpty.RotY += rR
butterflyEmpty.RotZ += rR
butterflyEmpty.SizeX += rR / 50
butterflyEmpty.SizeY += rR / 50
butterflyEmpty.SizeZ += rR / 50
###########################################################
# Create butterflies to be placed in the animation
# based on the initially defined butterfly
# consisting of two mesh objects and one empty object.
# This function makes use of Blender's Duplicate function,
# which duplicates those objects that are currently selected.
# This function all enables us to retain the parenting
# relationship of the 2 meshes to the Empty object as
# defined in the original setup (as per the challenge rules).
def createButterflies():
scene = Blender.Scene.GetCurrent()
empty = Blender.Object.Get("butterflyEmpty")
butterflyBody = Blender.Object.Get("butterflyBody")
butterflyWings = Blender.Object.Get("butterflyWings")
empty.sel = butterflyBody.sel = butterflyWings.sel = True
for a in range(howManyButterflies):
b = a + 1
Blender.Object.Duplicate()
rX = Rand(-.75, .75)
rY = Rand(-.75, .75)
rZ = Rand(-.75, .75)
rR = Rand(-5.0, 5.0)
randomizeButterflyLocation(b, rX, rY, rZ, rR)
# This mysterious cube is explained in the following
# setupEverything() function.
cubeMesh = Mesh.Primitives.Cube(.5)
cubeNew = scene.objects.new(cubeMesh, "DoneCube")
cubeNew.setLocation(0, 0, 0)
cubeNew.setSize(0, 0, 0)
###########################################################
# This is the initialization function. If the scene
# has already been set up, then it does nothing.
# This is important, since, when script links are
# activated and this entire script is invoked at
# each new frame, we do not want to have more
# butterflies added per frame. The script tests
# for the initialization in a way that can survive
# multiple Blender sessions by placing a "DoneCube"
# in the center of the scene. This cube is hidden
# and will not render, but its presence helps the
# script avoiding unintended reinitializations.
def setupEverything():
try:
test = Blender.Object.Get("DoneCube")
except:
createButterflies()
print "Initializing scene."
Blender.Redraw()
###########################################################
# Here we randomly animate each butterfly's wings
# and move/rotate each Empty, which moves/rotates
# each butterfly.
def animateButterflies():
objects = Blender.Object.Get()
for o in objects:
objName = str(o)
updateEveryXFrames = 8
updateFrame = currentFrame / updateEveryXFrames
if objName.find("butterflyWings") != -1:
butterflyMesh = o.getData(mesh = True)
if (updateFrame) == int(updateFrame):
rFlap = Rand(-2.5, 2.5)
wingVerts = butterflyMesh.getVertsFromGroup('OuterWing')
for v in wingVerts:
butterflyMesh.verts[v].co[2] = rFlap
butterflyMesh.update()
if objName.find("butterflyEmpty") != -1:
updateEveryXFrames = 3
updateFrame = currentFrame / updateEveryXFrames
if (updateFrame) == int(updateFrame):
rMove = Rand(-.3, .3)
o.LocX += (sin(currentFrame)*.01) + rMove
o.LocY += (sin(currentFrame)*.01) + rMove
rMove = Rand(-.3, .3)
o.LocZ += sin(currentFrame) * (rMove*2)
o.RotX += sin(currentFrame * rMove)
o.RotY += sin(currentFrame + rMove)
o.RotZ += sin(currentFrame / (rMove+1))
###########################################################
# The Main Program Begins Here!
setupEverything()
animateButterflies()
Here is the animation. (OpenGL/3D View animation; 1.5MB; Xvid encoded)
Animation was tested in Windows Media Player, VirtualDub, and VLC.
Here is a regular render, just for fun:

Here is the .blend file.
Well, this was another great challenge. Thanks to Koba for providing this great opportunity to learn and have some fun doing something completely different with Blender. I hope to see more participants and many future challenges.
Enjoy the weekend, everyone! 
RobertT