rotation via python does not the way i would it have expected I created a cylinder via python.
I rotated it it 2 times (y and z axis). Then moved it up.
Then i changed the origin to be in world center and rotated in on z - axis.
So the result is like this (which is ok)

then i added these line to my code
# expected: rotation &quot;in place&quot; - so same as before, but vertical
setOriginToGeometry(bpy.context.active_object)
bpy.ops.transform.rotate(value = math.pi / 2, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

and as i wrote in the comments i expected the green bar to rotate &quot;just in place&quot;, instead i got this:

so obviously i am doing and understanding something wrong, but what? Any help appreciated!
my code:
import bpy
import math

def setOriginToCursor(object):
    bpy.context.view_layer.objects.active = object
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

def setOriginToGeometry(object): 
    bpy.context.view_layer.objects.active = object
    bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN')

i = 0
name = &quot;object&quot;
halfPi = math.pi / 2
radius = 3
number_of_objects = 1

angle = 2 * math.pi / number_of_objects

bpy.ops.mesh.primitive_cylinder_add(radius=1, depth=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(0.1,  0.1, 1))

new_Name = name + '_' + str(i)
bpy.context.active_object.name = new_Name

# rotation 90 y-Axis, so i can see it from top view (result : horizontal)
bpy.ops.transform.rotate(value = halfPi, orient_axis='Y', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
# rotation 90 on z axis, so it is vertical
bpy.ops.transform.rotate(value = math.pi * 2 - angle * i + math.pi / 2, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
# move it up on y-axis
bpy.context.active_object.location[0] = math.sin(angle*i)*radius      
bpy.context.active_object.location[1] = math.cos(angle*i)*radius       
bpy.context.active_object.location[2] = 0



#i = 2


# works as expected  

setOriginToCursor(bpy.context.active_object)
# moved and rotated to the left from origin - horizontal
bpy.ops.transform.rotate(value = math.pi / 2, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

# expected: rotation &quot;in place&quot; - so same as before, but vertical
# but it is: in world origin :(
setOriginToGeometry(bpy.context.active_object)
bpy.ops.transform.rotate(value = math.pi / 2, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
Use variable names.
import bpy
context = bpy.context
scene = context.scene
ob = context.object

The  context variable step is for when your test code works, and you wish to make an operator, can very easily copy an paste blocks of code. To where  context is a usual suspect in operator and panel method arguments.
Reducing a line like
bpy.context.scene.cursor.location = bpy.context.active_object.location

to
scene.cursor.location = ob.location

Remove default settings from operators.
Sure can copy the complete operator call from the info window, but what of these settings do  you need to set? Consult the docs, if it's default it's not required, reducing
bpy.ops.transform.rotate(
    value = math.pi * 2 - angle * i + math.pi / 2, 
    orient_axis='Z', 
    orient_type='GLOBAL', 
    orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), 
    orient_matrix_type='GLOBAL', 
    constraint_axis=(False, False, True), 
    mirror=True, 
    use_proportional_edit=False, 
    proportional_edit_falloff='SMOOTH', 
    proportional_size=1, 
    use_proportional_connected=False, 
    use_proportional_projected=False
    )

to.
bpy.ops.transform.rotate(
    value = math.pi * 2 - angle * i + math.pi / 2, 
    orient_axis='Z'
    )

to rotate globally (the default) about 'Z'.
What I think the issue is.
If using set origin to cursor, pays to know where that cursor is, and unless it is a script where this is used and set by the user first, make sure its location is a known entity.
scene.cursor.location = (0, 0, 0) # so we know where it is
setOriginToGeometry(ob)
bpy.ops.transform.rotate(value = math.pi / 2, orient_axis='Z')

IMO better still, make it an argument and  pass it to your origin set method, and set it (and reset it) there
Or better still, just don't do it with operators, most of time they are not required &amp; IMO it will drive you nuts, so instead I'm....
Revisiting this answer.

Thank you very much for your answer batFinger. Unfortunately i do not
understand it. But that is my fault because i have just a few days
experience with Blender python and i am pretty proud i made it that
far (from my - i have no idea what i am doing - point of view ;).
Hopefully i do understand your answer in a few weeks when i am diving
deeper into that very amazing topic

This begs the question.. hows it going with operators?, am aware how we can become  attached to getting a script to work...(guilty myself on many an occasion) IMO once we &quot;See the light&quot; will never return to using code designed basically as a UI interface to do simple tasks like transforms (translate, rotate, scale).

In this example add the scaled cylinder at (0, 0, 0)
Emulate the edit mode rotation of 90 about X axis, and translation of 1 (radius) units in Y direction with a translation and rotation matrix.  The objects origin will remain at (0, 0, 0) and the mesh will be at 12 o'clock (top view) and can be simply rotated around the clock with its Z rotation property.
The Mesh.transform(matrix) uses the matrix supplied to transform all the vertices of the mesh in one fell swoop. A 4x4 (rowsxcolumns) transform matrix, like the matrix world is made up of its translation, rotation, scale parts
M = T @ R @ S 

Here we have use T and R
import bpy
from mathutils import Matrix
from math import pi

context = bpy.context
scene = context.scene
radius = 1
# create our object to array       
bpy.ops.mesh.primitive_cylinder_add(
        location=(0, 0, 0),
        scale=(0.1, 0.1, 1),
        )

ob = context.active_object
        
T = Matrix.Translation((0, radius, 0))
R = Matrix.Rotation(pi / 2, 4, 'X')
ob.data.transform(T @ R)

Effectively this has made our object lie in the XY plane, point up (+Y) and shifted its origin 1 down from its orginal location.