Today I found a quite interesting class searching the API: FamilyInstanceCreationData
By passing parameters, you can use doc.Create.NewFamilyInstances2() to generate all components at once.
This class can be used for modeling or adjusting components. The method comes with two methods. .axis && .RotateAngle can save the steps of using ElementTransformUtils.RotateElement() after generating components before. It is more concise at call level than generating one by one before. The time difference has not been tested yet. Below is the example in official documentation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
ICollection<ElementId> BatchCreateColumns(Autodesk.Revit.DB.Document document, Level level)
{
List<FamilyInstanceCreationData> fiCreationDatas = new List<FamilyInstanceCreationData>();

//ElementSet elementSet = null;
ICollection<ElementId> elementSet = null;

//Try to get a FamilySymbol
FamilySymbol familySymbol = null;
FilteredElementCollector collector = new FilteredElementCollector(document);
ICollection<Element> collection = collector.OfClass(typeof(FamilySymbol)).ToElements();
foreach (Element e in collection)
{
familySymbol = e as FamilySymbol;
if (null != familySymbol.Category)
{
if ("Structural Columns" == familySymbol.Category.Name)
{
break;
}
}
}

if (null != familySymbol)
{
//Create 10 FamilyInstanceCreationData items for batch creation
for (int i = 1; i < 11; i++)
{
XYZ location = new XYZ(i * 10, 100, 0);
FamilyInstanceCreationData fiCreationData =
new FamilyInstanceCreationData(location, familySymbol, level, StructuralType.Column);

if (null != fiCreationData)
{
fiCreationDatas.Add(fiCreationData);
}
}

if (fiCreationDatas.Count > 0)
{
// Create Columns
elementSet = document.Create.NewFamilyInstances2(fiCreationDatas);
}
else
{
throw new Exception("Batch creation failed.");
}
}
else
{
throw new Exception("No column types found.");
}

return elementSet;
}