Distribute copies.
Further to @moonboots answer can copy and distribute the object. Each copy shares the one mesh.
import bpy
from mathutils import Vector
from random import uniform
def array(context, count, rel_offset=Vector(), rnd_var_range=(0, 0), rnd_var_dir=Vector()):
scene = context.scene
for ob in context.selected_objects:
mw = ob.matrix_world
R = mw.to_quaternion().to_matrix()
offset = R * rel_offset.dot(ob.dimensions) * rel_offset.normalized()
copies = count - 1
for i in range(copies):
copy = ob.copy()
t = copy.matrix_world.translation
t += (i + 1) * offset
copy.delta_location = uniform(*rnd_var_range) * rnd_var_dir
copy.select = True
scene.objects.link(copy)
# test call
context = bpy.context
array(context,
count = 5,
rel_offset = Vector((1.1 , 0, 0)),
rnd_var_dir = Vector((0, 1, 0)),
rnd_var_range = (-1, 1))
array(context,
count = 5,
rel_offset = Vector((0, 0, 1.1)),
rnd_var_dir = Vector((0, 1, 0)),
rnd_var_range = (-1, 1))

Result of running script with Suzanne selected. The variation of both arrays in test call are in local Y direction.
The same script updated to Blender 2.8 API
import bpy
from mathutils import Vector
from random import uniform
def array(context, count, rel_offset=Vector(), rnd_var_range=(0, 0), rnd_var_dir=Vector()):
scene = context.scene
for ob in context.selected_objects:
mw = ob.matrix_world
R = mw.to_quaternion().to_matrix()
offset = R @ (rel_offset.dot(ob.dimensions) * rel_offset.normalized())
copies = count - 1
for i in range(copies):
copy = ob.copy()
t = copy.matrix_world.translation
t += (i + 1) * offset
copy.delta_location = uniform(*rnd_var_range) * rnd_var_dir
context.collection.objects.link(copy)
copy.select_set(state=True)
context.view_layer.objects.active = copy
# test call
context = bpy.context
array(context,
count = 5,
rel_offset = Vector((1.1 , 0, 0)),
rnd_var_dir = Vector((0, 1, 0)),
rnd_var_range = (-1, 1))
array(context,
count = 5,
rel_offset = Vector((0, 0, 1.1)),
rnd_var_dir = Vector((0, 1, 0)),
rnd_var_range = (-1, 1))
Main changes are:
- @ operator is now used for matrix/vector component-wise multiplication
- selection of an object in context is now done with
copy.select_set(state=True)
- The link must now be done via collections and not view_layer